package org.thanos.demo.config;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.ds.ItemDataSource;
import com.baomidou.dynamic.datasource.exception.CannotFindDataSourceException;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import org.thanos.demo.service.TenantService;
import org.thanos.demo.service.TenantVO;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Objects;

@Service("dataSourceManager")
@Configuration
@ConditionalOnProperty(
        prefix = "dynamic-ds",
        name = {"enabled"},
        havingValue = "true"
)
public class DynamicDataSourceManager implements DataSourceManager {

    private static final Logger log = LoggerFactory.getLogger(DynamicDataSourceManager.class);
    @Value("${spring.datasource.driver-class-name:com.mysql.cj.jdbc.Driver}")
    private String driverClassName;

    @Autowired
    private TenantService tenantService;

    @Autowired
    private DynamicRoutingDataSource dynamicRoutingDataSource;

    @Autowired
    @Qualifier("hikariDataSourceCreator")
    private DataSourceCreator dataSourceCreator;

    public DynamicDataSourceManager() {
    }

    @Override
    public DataSource getDbSource(Integer siteId, TenantVO siteDb) {
        DataSource dynamicDataSource = this.getDataSourceIgnoreMasterNotFoundException(siteDb.getDbName());
        ItemDataSource determine = (ItemDataSource) this.determineDatasourceIgnoreMasterNotException();
        if (dynamicDataSource != null && determine != null) {
            determine.getName();
        }
        Boolean result = this.checkDataSource(siteDb.getUrl(), siteDb.getUser(), siteDb.getPassword());
        if (Boolean.TRUE.equals(result)) {
            DataSourceProperty dataSourceProperty = new DataSourceProperty();
            dataSourceProperty.setPoolName(siteDb.getId().toString());
            dataSourceProperty.setUrl(siteDb.getUrl());
            dataSourceProperty.setUsername(siteDb.getUser());
            dataSourceProperty.setPassword(siteDb.getPassword());
            dataSourceProperty.setDriverClassName(this.driverClassName);
            DataSource dataSource = this.dataSourceCreator.createDataSource(dataSourceProperty);
            this.dynamicRoutingDataSource.addDataSource(dataSourceProperty.getPoolName(), dataSource);
            dynamicDataSource = this.getDataSourceIgnoreMasterNotFoundException(siteDb.getDbName());
            return dynamicDataSource;
        } else {
            return null;
        }
    }

    private Boolean checkDataSource(String jdbcUrl, String dbUser, String dbPassword) {
        Connection connection = null;

        Boolean var6;
        try {
            Class.forName(this.driverClassName);
            connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPassword);
            return Boolean.TRUE;
        } catch (Exception var10) {
            log.error("Failed to initialize database: {}. {}", jdbcUrl, var10);
            var6 = Boolean.FALSE;
        } finally {
            this.closeConnection(connection);
        }

        return var6;
    }

    private void closeConnection(Connection connection) {
        try {
            if (connection == null) {
                return;
            }

            connection.close();
        } catch (Exception var3) {
            log.error("Failed to close connection.");
        }

    }

    private DataSource getDataSourceIgnoreMasterNotFoundException(String dsName) {
        try {
            return this.dynamicRoutingDataSource.getDataSource(dsName);
        } catch (CannotFindDataSourceException var3) {
            if (var3.getMessage().contains("primary datasource")) {
                return null;
            } else {
                throw var3;
            }
        }
    }

    private DataSource determineDatasourceIgnoreMasterNotException() {
        try {
            return this.dynamicRoutingDataSource.determineDataSource();
        } catch (CannotFindDataSourceException var2) {
            if (var2.getMessage().contains("primary datasource")) {
                return null;
            } else {
                throw var2;
            }
        }
    }
}
